﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace YWM.Common.Extensions
{
    public static class AssemblyExtensions
    {
        public static List<Type> GetTypes(this AppDomain domain, Func<Type, bool> predicate)
        {
            List<Type> types = new List<Type>();
            List<Assembly> assemblies = domain.GetReferanceAssemblies();
            foreach (Assembly item in assemblies)
            {
                IEnumerable<Type> itemTypes = item.GetTypes().Where(predicate);
                types.AddRange(itemTypes);
            }
            return types;
        }

        public static List<Assembly> GetReferanceAssemblies(this AppDomain domain, bool includeSystem = false)
        {
            List<Assembly> list = new List<Assembly>();
            domain.GetAssemblies();
            foreach (Assembly assembly in domain.GetAssemblies())
            {
                if (!includeSystem && assembly.GetName().Name.IsSystemAssembly())
                {
                    continue;
                }
                GetReferanceAssemblies(assembly, list, includeSystem);
            };
            return list;
        }

        static void GetReferanceAssemblies(Assembly assembly, List<Assembly> list, bool includeSystem)
        {
            foreach (AssemblyName assemblyName in assembly.GetReferencedAssemblies())
            {
                if (!includeSystem && assemblyName.Name.IsSystemAssembly())
                {
                    continue;
                }
                Assembly childAssembly = Assembly.Load(assemblyName);
                if (!list.Contains(childAssembly))
                {
                    list.Add(childAssembly);
                    GetReferanceAssemblies(childAssembly, list, includeSystem);
                }
            };
        }

        static bool IsSystemAssembly(this string name)
        {
            string[] equals = new string[] { "System", "mscorlib", "PresentationFramework", "WindowsBase", "PresentationCore", "DirectWriteForwarder", "netstandard", "UIAutomationTypes", "UIAutomationProvider", "ReachFramework", "PresentationUI" };
            string[] contains = new string[] { "System.", "Microsoft." };
            if (equals.Contains(name))
            {
                return true;
            }
            if (contains.FirstOrDefault(c => name.StartsWith(c)) != null)
            {
                return true;
            }
            return false;
        }
    }
}
